home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / COMM / RPL60 / RPL.PAS < prev    next >
Pascal/Delphi Source File  |  1992-12-31  |  24KB  |  712 lines

  1. {$A+,B+,E-,F-,I+,L+,N-,O-,R-,S-,V-} { TP6 Compiler Options }
  2. {$M 65500,65500,655000}
  3. {*source code copyright (c) 1985, by TurboPower Software*}
  4. { "UpGraded" to compile under TP6.0 by Steve Whalen 3-16-92 }
  5.  
  6. program Rpl;
  7.   {-select text lines, match and replace strings}
  8.  
  9. uses
  10.   { Mon, }
  11.   OpCrt,
  12.   Dos,
  13.   OpDos,
  14.   OpString;                       { for UpCaseMac }
  15.  
  16. const
  17.   Copyright      : String[79] = 'RPL - Pattern Replacer. Copyright (c) 1985 by TurboPower Software.';
  18.   Version        : String[79] = 'All Rights Reserved. Version 1.21.60b';
  19.   OptionDelim    = '-';           {character used to introduce a command line option}
  20.   Null           = #00;
  21.   EndStr         = #255;
  22.   NewLine        = #13#10;
  23.   Dash           = '-';
  24.   Esc            = '\';
  25.   Any            = '?';
  26.   Closure        = '*';
  27.   ClosurePlus    = '+';
  28.   MaybeOne       = '!';
  29.   Bol            = '^';
  30.   Eol            = '$';
  31.   Ccl            = '[';
  32.   Negate         = '^';
  33.   CclEnd         = ']';
  34.   BTag           = '{';
  35.   ETag           = '}';
  36.   BGroup         = '(';
  37.   EGroup         = ')';
  38.   Alter          = '#';
  39.   Ditto          = '&';
  40.   lSpace         = 's';
  41.   lNewline       = 'n';
  42.   lTab           = 't';
  43.   lBackSpace     = 'b';
  44.   lReturn        = 'r';
  45.   lFeed          = 'l';
  46.   lHex           = 'h';
  47.   lWordDelim     = 'w';
  48.   lInput         = 'i';
  49.   lOutput        = 'o';
  50.   lPipe          = 'p';
  51.   lNil           = 'z';
  52.   wDelimString   = #9#32'!"&()*+,-./:;<=>?@[\]^`{|}~';
  53.   LabLen         = 1024;
  54.   TokLen         = 255;           {max length of a command line token}
  55.   MaxTok         = 10;            {max number of tokens on command line}
  56.   BufLen         = 16384;
  57.   LowMono        = LightGray;
  58.   HighMono       = White;
  59.   LowColor       = Cyan;
  60.   HighColor      = Yellow;
  61.  
  62. type
  63.   FileType       = Text;
  64.   Line           = record
  65.                      Length         : Integer;
  66.                      Val            : array[1..LabLen] of Char;
  67.                    end;
  68.   BufLine        = array[1..BufLen] of Char;
  69.   LongString     = String[255];
  70.   PatLine        = String[255];
  71.   Tokens         = (tNil, tLitChar, tCcl, tnCcl, tClosure, tMaybeOne,
  72.                     tAny, tBol, tEol, tGroup, tbTag, teTag, tDitto);
  73.   PatPtr         = ^PatRecord;
  74.   lsPtr          = ^LongString;
  75.   PatRecord      = record
  76.                      Tok            : Tokens;
  77.                      One            : Char;
  78.                      NexTok         : Boolean;
  79.                      StrPtr         : lsPtr;
  80.                      NestPtr, Next  : PatPtr;
  81.                    end;
  82.   TagLevel       = -1..9;
  83.   Flag           = array[1..LabLen] of TagLevel;
  84.   FileString     = String[64];
  85.   RegPack        = Registers;
  86.   Token          = String[TokLen];
  87.   ArgArray       = array[1..MaxTok] of Token;
  88.   Message        = String[79];
  89. var
  90.   argc           : Integer;       {argument count (number of tokens)}
  91.   argv           : ArgArray;      {elements are the tokens found on the command line}
  92.   ErrMess        : Message;       {error message, if any, returned from getcom}
  93.   Path, Out1, Out2 : LongString;
  94.   Rep, Sel, Pat  : PatLine;
  95.   OutLine        : Line;
  96.   SelRec, PatRec, RepRec : PatPtr;
  97.   CinF           : FileType;
  98.   ConsoleIn, ConsoleOut, FileOpen, Matching, Monly, UnSelOut,
  99.   ShowLines, IgnoreCase, Debug, ShowStatus, InterActive,
  100.   InputOpen, CountOnly, Avoiding, Selecting, Replacing : Boolean;
  101.   Reg            : RegPack;
  102.   InHandle, SelectCnt, MatchCnt, wrCnt, ScreenLine,
  103.   lNum, OutHandle : Integer;
  104.   tStart, tStop, Rate : Real;
  105.   nStr           : String[6];
  106.  
  107.   {$I rpllow.inc}
  108.   {$I rplfind.inc}
  109.   {$I rplpat.inc}
  110.   {$I rplmat.inc}
  111.   {$I rplrep.inc}
  112.   {$I RplHelp.Inc}
  113.  
  114.   procedure ParseCommand(UsePsp : Boolean; cLine : LongString);
  115.     {-interpret a command line to get options and templates}
  116.   var
  117.     tLine          : LongString;
  118.     i              : Integer;
  119.     c              : Char;
  120.     cfName         : FileString;
  121.     HaltSoon, cFileToRead, OK : Boolean;
  122.  
  123.   begin
  124.     OK := True;
  125.     if not(UsePsp) then OK := GetCom(UsePsp, cLine, ErrMess);
  126.     if OK and (argc > 0) then begin
  127.       HaltSoon := False;
  128.       cFileToRead := False;
  129.       i := 1;
  130.       while i <= argc do begin
  131.         if argv[i][1] = OptionDelim then begin
  132.           {start of a command option}
  133.           c := UpCaseMac(argv[i][2]);
  134.           {make sure it really is meant to be a command}
  135.           if (c <> 'O') and (c <> 'U') then begin
  136.             if Length(argv[i]) <> 2 then begin
  137.               WrL('unrecognized command option '+argv[i]);
  138.               HaltSoon := True;
  139.             end;
  140.           end else begin
  141.             if Length(argv[i]) <> 3 then begin
  142.               WrL('unrecognized command option '+argv[i]);
  143.               HaltSoon := True;
  144.             end;
  145.           end;
  146.           case c of
  147.             '?' : WriteHelp;
  148.             'I' : IgnoreCase := True;
  149.             'N' : ShowLines := True;
  150.             'F' : begin           {finding a command file -- note nesting OK}
  151.                     i := Succ(i);
  152.                       if i <= argc then OK := True else OK := False;
  153.                     if OK then begin
  154.                       cFileToRead := True;
  155.                       cfName := argv[i];
  156.                       DefaultExtension('PAT', cfName);
  157.                     end else begin
  158.                       WrL('improper command file specification '+argv[Pred(i)]);
  159.                       HaltSoon := True;
  160.                     end;
  161.                   end;
  162.             'U' : begin           {unselected lines}
  163.                     c := UpCaseMac(argv[i][3]);
  164.                     if c = 'S' then UnSelOut := True
  165.                     else begin
  166.                       WrL('unrecognized command option '+argv[i]);
  167.                       HaltSoon := True;
  168.                     end;
  169.                   end;
  170.             'O' : begin           {output selection option}
  171.                     c := UpCaseMac(argv[i][3]);
  172.                     case c of
  173.                       'M' : Monly := True;
  174.                       'C' : CountOnly := True;
  175.                     else
  176.                       WrL('unrecognized output selector -O'+c);
  177.                       HaltSoon := True;
  178.                     end;
  179.                   end;
  180.             'S' : begin           {selection pattern follows}
  181.                     if not(Avoiding) then begin
  182.                       Selecting := True;
  183.                       i := Succ(i);
  184.                         if i <= argc then Sel := argv[i]+EndStr else begin
  185.                           WrL('didn''t find select pattern');
  186.                           Halt;
  187.                         end;
  188.                     end;
  189.                   end;
  190.             'V' : begin
  191.                     if not(Selecting) then begin
  192.                       Avoiding := True;
  193.                       i := Succ(i);
  194.                         if i <= argc then Sel := argv[i]+EndStr else begin
  195.                           WrL('didn''t find select pattern');
  196.                           HaltSoon := True;
  197.                         end;
  198.                     end;
  199.                   end;
  200.             'M' : begin
  201.                     Matching := True;
  202.                     i := Succ(i);
  203.                       if i <= argc then Pat := argv[i]+EndStr else begin
  204.                         WrL('didn''t find match pattern');
  205.                         HaltSoon := True;
  206.                       end;
  207.                   end;
  208.             'R' : begin
  209.                     Replacing := True;
  210.                     i := Succ(i);
  211.                       if i <= argc then Rep := argv[i]+EndStr else begin
  212.                         {it must specify a null replace pattern}
  213.                         Rep := EndStr;
  214.                       end;
  215.                   end;
  216.             'D' : Debug := True;
  217.           else
  218.             WrL('unrecognized command option -'+c);
  219.             HaltSoon := True;
  220.           end;
  221.         end else begin
  222.           if argv[i] = '?' then begin
  223.             WriteHelp;
  224.           end else begin
  225.             {must be a file specification}
  226.             {IF consolein AND NOT(inputopen) THEN BEGIN}
  227.             {ignore it if another file is already open}
  228.             OpenFile(argv[i], InHandle);
  229.             {map it onto the standard input}
  230.             ForceDup(InHandle, 0);
  231.             CloseFile(InHandle);
  232.             InputOpen := True;
  233.             InHandle := 0;
  234.             {END;}
  235.           end;
  236.         end;
  237.         i := Succ(i);
  238.       end;
  239.       {read a command file if called for}
  240.       if cFileToRead then begin
  241.         OK := FoundFile(cfName, Path, CinF);
  242.         if OK then begin
  243.           ReadLn(CinF, tLine);
  244.           Close(CinF);
  245.           ParseCommand(False, tLine);
  246.         end;
  247.       end;
  248.       {build tokenized patterns, only after all command files are read}
  249.       if UsePsp or InterActive then begin
  250.         if Selecting and (SelRec = nil) then
  251.           if not(GetPat(Sel, SelRec)) then begin
  252.             WrL('bad select pattern: '+Sel);
  253.             HaltSoon := True;
  254.           end;
  255.         if Avoiding and (SelRec = nil) then
  256.           if not(GetPat(Sel, SelRec)) then begin
  257.             WrL('bad avoid pattern: '+Sel);
  258.             HaltSoon := True;
  259.           end;
  260.         if Matching and (PatRec = nil) then
  261.           if not(GetPat(Pat, PatRec)) then begin
  262.             WrL('bad match pattern: '+argv[i]);
  263.             HaltSoon := True;
  264.           end;
  265.         if Replacing and (RepRec = nil) then
  266.           if not(GetRep(Rep, RepRec)) then begin
  267.             WrL('bad replace pattern: '+argv[i]);
  268.             HaltSoon := True;
  269.           end;
  270.  
  271.         {check for errors}
  272.         if not(Matching or Selecting or Avoiding) then begin
  273.           WrL('must specify at least a match, select or avoid pattern');
  274.           HaltSoon := True;
  275.         end;
  276.         if ConsoleIn and not(InputOpen) then begin
  277.           WrL('must specify an input file');
  278.           HaltSoon := True;
  279.         end;
  280.         if Replacing and not(Matching) then begin
  281.           WrL('if a replace pattern is specified, a match pattern must also be entered');
  282.           HaltSoon := True;
  283.         end;
  284.         {don't get putl confused}
  285.         if CountOnly then ShowLines := False;
  286.       end;
  287.     end else begin
  288.       WrL('must specify at least a match or select pattern');
  289.       HaltSoon := True;
  290.     end;
  291.     if HaltSoon then begin
  292.       if InputOpen then CloseFile(InHandle);
  293.       WrL('type RPL -? for help');
  294.       Halt;
  295.     end;
  296.   end;                            {parsecommand}
  297.  
  298.   procedure GetInputs;
  299.     {-prompt for inputs}
  300.   label 1;
  301.   var
  302.     fName          : FileString;
  303.     ComFile, Done  : Boolean;
  304.     cLine          : PatLine;
  305.     c              : Char;
  306.  
  307.     function RealDiskFile(var fName : FileString; var UseConsole : Boolean) : Boolean;
  308.       {-return true if fname is a disk file and not a device}
  309.       {-not strictly accurate but consistent with DOS behavior}
  310.     const
  311.       NumDevs        = 22;        {!!! .60b ... added Com3 & Com4 }
  312.       DevNames       : array[1..NumDevs] of String[5] =
  313.       ('LPT1', 'LPT2', 'LPT3', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4', 'PRN', 'CON', 'NUL',
  314.        'LPT1:', 'LPT2:', 'LPT3:', 'AUX:', 'COM1:', 'COM2:', 'COM3:', 'COM4:', 'PRN:', 'CON:', 'NUL:');
  315.     var
  316.       i, l           : Byte;
  317.       tName          : FileString;
  318.     begin
  319.       RealDiskFile := True;
  320.       UseConsole := False;
  321.       i := Pos('.', fName);
  322.         if i > 0 then tName := Copy(fName, 1, Pred(i)) else tName := fName;
  323.       l := Length(tName);
  324.       for i := 1 to l do tName[i] := UpCaseMac(tName[i]);
  325.       i := 1;
  326.       while i <= NumDevs do begin
  327.         if tName = DevNames[i] then begin
  328.           RealDiskFile := False;
  329.           UseConsole := (DevNames[i] = 'CON') or (DevNames[i] = 'CON:');
  330.           {remove colon if at end of name}
  331.             if tName[l] = ':' then fName := Copy(tName, 1, Pred(l)) else fName := tName;
  332.           i := NumDevs;
  333.         end;
  334.         i := Succ(i);
  335.       end;
  336.     end;                          {realdiskfile}
  337.  
  338.     function CheckPat(Pat : PatLine; var PatRec : PatPtr) : Boolean;
  339.       {-build match pattern and return true if ok}
  340.     begin
  341.       if GetPat(Pat, PatRec) then begin
  342.         CheckPat := True;
  343.       end else begin
  344.         WrL('bad match pattern. try again....');
  345.         CheckPat := False;
  346.       end;
  347.     end;                          {checkpat}
  348.  
  349.   begin
  350.     InterActive := True;
  351. 1:
  352.     if ConsoleIn then begin
  353.       Wr('Enter name of input text file: ');
  354.       ReadLn(fName);
  355.       if fName = '' then Halt;
  356.       OpenFile(fName, InHandle);
  357.       {map it onto the standard input}
  358.       ForceDup(InHandle, 0);
  359.       CloseFile(InHandle);
  360.       InputOpen := True;
  361.       InHandle := 0;
  362.     end;
  363.  
  364.     WrL('');
  365.     Wr('Do you want to read a command line file? (Y/N, <cr> for N) ');
  366.     ComFile := ReadYesNo(False);
  367.  
  368.     if ComFile then begin
  369.       WrL('');
  370.       repeat
  371.         Wr('Enter name of command line file: ');
  372.         ReadLn(fName);
  373.         if Length(fName) > 0 then begin
  374.           DefaultExtension('PAT', fName);
  375.         end else Halt;
  376.         Done := FoundFile(fName, Path, CinF);
  377.       until Done;
  378.       ReadLn(CinF, cLine);
  379.       Close(CinF);
  380.       ParseCommand(False, cLine);
  381.     end else begin
  382.       {no command line file}
  383.       WrL('');
  384.       Wr('Do you want to specify a select criterion? (Y/N, <cr> for N) ');
  385.       Selecting := ReadYesNo(False);
  386.       if not(Selecting) then begin
  387.         WrL('');
  388.         Wr('Do you want to specify an avoid criterion? (Y/N, <cr> for N) ');
  389.         Avoiding := ReadYesNo(False);
  390.       end;
  391.  
  392.       if Avoiding or Selecting then begin
  393.         WrL('');
  394.         repeat
  395.           Wr('enter select/avoid expression: ');
  396.           ReadLn(Pat);
  397.           if Length(Pat) = 0 then Halt;
  398.           Pat := Pat+EndStr;
  399.           Done := CheckPat(Pat, SelRec);
  400.         until Done;
  401.         WrL('');
  402.         Wr('Do you want to output non-selected lines? (Y/N, <cr> for N) ');
  403.         UnSelOut := ReadYesNo(False);
  404.         WrL('');
  405.         Wr('Do you want to specify a match criterion? (Y/N, <cr> for Y) ');
  406.         Matching := ReadYesNo(True);
  407.       end;
  408.  
  409.       if Matching or not(Selecting or Avoiding) then begin
  410.         WrL('');
  411.         repeat
  412.           Wr('enter match expression: ');
  413.           ReadLn(Pat);
  414.           if Length(Pat) = 0 then Halt;
  415.           Pat := Pat+EndStr;
  416.           Done := CheckPat(Pat, PatRec);
  417.           Matching := True;
  418.         until Done;
  419.       end;
  420.  
  421.       if Matching then begin
  422.         WrL('');
  423.         Wr('Do you want to do replacements? (Y/N, <cr> for Y) ');
  424.         Replacing := ReadYesNo(True);
  425.         if Replacing then begin
  426.           WrL('');
  427.           repeat
  428.             Wr('enter replace expression: ');
  429.             ReadLn(Rep);
  430.             Rep := Rep+EndStr;
  431.             if GetRep(Rep, RepRec) then begin
  432.               Done := True;
  433.               if Debug then begin
  434.                 Wr('replace pattern: '); WritePat(RepRec); WrL('');
  435.               end;
  436.             end else begin
  437.               WrL('bad replace pattern. try again....');
  438.               Done := False;
  439.             end;
  440.           until Done;
  441.           WrL('');
  442.           Wr('Do you want to output only modified lines? (Y/N, <cr> for N) ');
  443.           Monly := ReadYesNo(False);
  444.         end;
  445.       end;
  446.  
  447.       WrL('');
  448.       Wr('Do you want to output only the matched line count? (Y/N, <cr> for N) ');
  449.       CountOnly := ReadYesNo(False);
  450.  
  451.       if not(CountOnly) then begin
  452.         WrL('');
  453.         Wr('Do you want to show line numbers on output lines? (Y/N, <cr> for N) ');
  454.         ShowLines := ReadYesNo(False);
  455.       end;
  456.     end;
  457.  
  458.     if ConsoleOut then begin
  459.       {output has not already been redirected}
  460.       WrL('');
  461.       Wr('Enter file name where output will be sent (<cr> for screen): ');
  462.       ReadLn(fName);
  463.  
  464.       if Length(fName) > 0 then begin
  465.         {open for writing -- we don't check for overwrite}
  466.         FileOpen := RealDiskFile(fName, ConsoleOut);
  467.         CreateFile(fName, OutHandle);
  468.       end;                        {outhandle defaults to 1 (standard output)}
  469.     end;
  470.  
  471.     WrL('');
  472.     Wr('OK to proceed? (Y/N) ');
  473.     repeat
  474.       c := ReadKey;
  475.       c := UpCaseMac(c);
  476.     until (c in ['Y', 'N']);
  477.     WrL(c);
  478.     WrL('');
  479.     if c = 'N' then begin
  480.       if FileOpen then CloseFile(OutHandle);
  481.       goto 1;
  482.     end;
  483.  
  484.   end;                            {getinputs}
  485.  
  486.   procedure ProcessLine(Lin : Line);
  487.     {-process an input line and send to output}
  488.   var
  489.     mLin, Sub      : Line;
  490.     GoodLine       : Boolean;
  491.     Temp           : String[2];
  492.   begin
  493.     lNum := Succ(lNum);
  494.     if lNum < 0 then lNum := 0;
  495.     {    IF breakpressed THEN breakhalt; }
  496.  
  497.     if ShowStatus and ((lNum mod 8) = 0) then begin
  498.       Wr(^H^H^H^H^H^H+LongIntForm('######', lNum));
  499.     end;
  500.  
  501.     Temp := NewLine;
  502.     AppendS(Lin.Val, Lin.Length, Temp[1], 2, Lin);
  503.     Temp := EndStr;
  504.     AppendS(Lin.Val, Lin.Length, Temp[1], 1, mLin);
  505.  
  506.     if Selecting then begin
  507.       GoodLine := Match(mLin, SelRec);
  508.     end else if Avoiding then begin
  509.       GoodLine := not(Match(mLin, SelRec));
  510.     end else GoodLine := True;
  511.  
  512.     if GoodLine then begin
  513.       {met select criterion, perhaps by default}
  514.       SelectCnt := Succ(SelectCnt);
  515.       if Replacing then begin
  516.         if Monly then begin
  517.           {we only want to replace and output lines that have a match}
  518.           GoodLine := Match(mLin, PatRec);
  519.         end;
  520.         if GoodLine then begin
  521.           SubLine(mLin, PatRec, RepRec, Sub);
  522.           if not(CountOnly) then PutL(Sub);
  523.           {subline keeps a count of matched lines and replaced patterns}
  524.         end;
  525.       end else if Matching then begin
  526.         GoodLine := Match(mLin, PatRec);
  527.         {met match criterion}
  528.         if GoodLine then begin
  529.           MatchCnt := Succ(MatchCnt);
  530.           if not(CountOnly) then PutL(Lin);
  531.         end;
  532.       end else begin
  533.         {we are neither matching nor replacing, just selecting}
  534.         {output the selected line}
  535.         if not(CountOnly) then PutL(Lin);
  536.       end;
  537.     end else begin
  538.       {non-selected line, do we print it?}
  539.       if UnSelOut and not(CountOnly) then PutL(Lin);
  540.     end;
  541.   end;                            {processline}
  542.  
  543.   procedure GetFromFile;
  544.     {-read chunks from a file, process and send to standard output}
  545.   var
  546.     c              : Char;
  547.     Done           : Boolean;
  548.     l              : Line;
  549.     lt             : array[0..1] of BufLine;
  550.     lCount         : array[0..1] of Integer;
  551.     lStart, InExt, i, lPos : Integer;
  552.   begin
  553.     InExt := 0; lStart := 0; ScreenLine := 1;
  554.     repeat
  555.       {get a new chunk}
  556.       Done := GetChunk(lt[InExt], lCount[InExt]);
  557.       {build a line terminated by CR/LF, EOF, or max length}
  558.       i := 1; lPos := lStart;
  559.       while i <= lCount[InExt] do begin
  560.         c := lt[InExt][i];
  561.         if c = #13 then begin
  562.           {found the end of a line}
  563.           l.Length := lPos;
  564.           ProcessLine(l);
  565.           lPos := 0;
  566.         end else if c = #26 then begin
  567.           {found end of file marker}
  568.           l.Length := lPos;
  569.           if lPos > 0 then ProcessLine(l);
  570.           Done := True;
  571.           i := LabLen;
  572.         end else if c <> #10 then begin
  573.           if lPos < LabLen then begin
  574.             {append this character to current line}
  575.             {ignore characters beyond the limit of length}
  576.             lPos := Succ(lPos);
  577.             l.Val[lPos] := c;
  578.           end else begin
  579.             if ShowStatus then begin
  580.               Wr(^m);
  581.             end else begin
  582.               WrL(''); WrL('');
  583.             end;
  584.             WrL('WARNING: line '
  585.                 +LongIntForm('######', Succ(lNum))+' exceeds '
  586.                 +Long2Str(LabLen)+' characters. Line broken...');
  587.             WrL('');
  588.             if ShowStatus then begin
  589.               Wr('line number: '+LongIntForm('######', Succ(lNum)));
  590.             end;
  591.             l.Length := lPos;
  592.             ProcessLine(l);
  593.             lPos := 0;
  594.           end;
  595.         end;
  596.         i := Succ(i);
  597.       end;
  598.       InExt := 1-InExt;           {switch to the other temporary line}
  599.       lStart := lPos;             {continue the line being built}
  600.       if Done and (c <> #26) and (c <> #13) and (c <> #10) then begin
  601.         {last line of file did not end with #26 or #13}
  602.         l.Length := lPos;
  603.         ProcessLine(l);
  604.       end;
  605.  
  606.     until Done;
  607.   end;                            {getfromfile}
  608.  
  609.   (*
  610.   procedure WriteDebug;
  611.     {-display the global flags and settings}
  612.   begin
  613.     if Matching then begin
  614.       Wr('mat: '); WritePat(PatRec); WrL('');
  615.     end;
  616.     if Replacing then begin
  617.       Wr('rep: '); WritePat(RepRec); WrL('');
  618.     end;
  619.     if Selecting or Avoiding then begin
  620.       Wr('sel: '); WritePat(SelRec); WrL('');
  621.     end;
  622.     WriteLn('sel: ', Selecting, ' avo: ', Avoiding, ' mat: ', Matching, ' rep: ', Replacing);
  623.     WriteLn(' conout: ', ConsoleOut, ' conin: ', ConsoleIn, ' inopen: ', InputOpen);
  624.     WriteLn('cnt: ', CountOnly, ' outhand: ', OutHandle, ' inhand: ', InHandle);
  625.     WrL('');
  626.   end;                            {WriteDebug}
  627.   *)
  628.  
  629. begin
  630.   CheckBreak := True;
  631.   DirectVideo := False;
  632.   TextBackGround(Black);
  633.   HiVid;
  634.   WrL('');
  635.  
  636.   {set defaults}
  637.   OutHandle := 1; FileOpen := False; InHandle := 0;
  638.   Selecting := False; Avoiding := False;
  639.   Matching := False; Replacing := False;
  640.   ShowLines := False; CountOnly := False; IgnoreCase := False;
  641.   UnSelOut := False; Monly := False; Debug := False;
  642.   lNum := 0; MatchCnt := 0; SelectCnt := 0; wrCnt := -32766;
  643.   SelRec := nil; PatRec := nil; RepRec := nil; InterActive := False;
  644.   ConsoleOut := IoStat(1);
  645.   ConsoleIn := IoStat(0);
  646.   InputOpen := not(ConsoleIn);
  647.  
  648.   {get inputs}
  649.   if GetCom(True, '', ErrMess) then begin
  650.  
  651.     if argc > 0 then ParseCommand(True, '') else GetInputs;
  652.  
  653.     {reassure that the input was read right}
  654.     {if Debug then WriteDebug;}
  655.  
  656.     tStart := TimeMs/1000; { !!!.60b } { convert Msec to Seconds }
  657.     ShowStatus := not(ConsoleOut) or CountOnly;
  658.     if ShowStatus then begin
  659.       Wr('line number: '+'     1');
  660.     end;
  661.  
  662.     {read the input file, perform matching, and Wr output}
  663.     GetFromFile;
  664.  
  665.     tStop := TimeMs/1000; { !!!.60b } { convert Msec to Seconds }
  666.     if ShowStatus then begin
  667.       Wr(^m);
  668.     end else begin
  669.       WrL('');
  670.     end;
  671.  
  672.     WrL('lines input: '+Long2Str(lNum)+'  lines selected: '+Long2Str(SelectCnt));
  673.     Wr('lines matched: '+Long2Str(MatchCnt)+'  patterns replaced: ');
  674.     if wrCnt >= 32766 then
  675.       WrL('> 32766')
  676.     else
  677.       WrL(Long2Str(wrCnt+32766));
  678.     if (tStop-tStart) > 0 then begin
  679.       Rate := lNum/(tStop-tStart);
  680.       WrL('scan rate: '+Form('####.#', Rate)+' LPS');
  681.     end;
  682.     WrL('');
  683.  
  684.     if CountOnly and not(ConsoleOut) then begin
  685.       WrL('');
  686.       Str(SelectCnt, nStr);
  687.       Out1 := '#lines selected: '+nStr;
  688.       Str(MatchCnt, nStr);
  689.       Out2 := '  #lines matched: '+nStr;
  690.       AppendS(Out1[1], Length(Out1), Out2[1], Length(Out2), OutLine);
  691.       Str((Int(wrCnt)+32766.0):5:0, nStr);
  692.       Out1 := '  #patterns replaced: ';
  693.       if wrCnt = 32766 then Out1 := Out1+'>';
  694.       Out1 := Out1+nStr+#13+#10;
  695.       AppendS(OutLine.Val, OutLine.Length, Out1[1], Length(Out1), OutLine);
  696.       PutL(OutLine);
  697.     end;
  698.  
  699.     if not(ConsoleOut) or FileOpen then begin
  700.       ShowLines := False;         {don't print a line number with EOF}
  701.       (*
  702.       outline.val[1] := ^Z; {choice of whether to end with ^Z or not}
  703.       outline.length := 1;
  704.       putl(outline);
  705.       *)
  706.       CloseFile(OutHandle);
  707.     end;
  708.     if InputOpen then CloseFile(InHandle);
  709.  
  710.   end else WrL(ErrMess);
  711. end.                              {rpl}
  712.